﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using FluentAssertions;

using Ncqrs.Commands;
using Ncqrs.EventSourcing.EntityFramework;
using Ncqrs.EventSourcing.Storage;

using TheKitchen.Commanding.Commands;

namespace TheKitchen.Host.Specs
{
    [TestClass]
    public class BinaryPropertySerializerSpecs
    {
        [TestMethod]
        public void When_round_tripping_it_should_include_all_properties()
        {
            //-----------------------------------------------------------------------------------------------------------
            // Arrange
            //-----------------------------------------------------------------------------------------------------------
            var command = new AddNewRecipeCommand
            {
                Name = "Macaroni with chees",
                Description = "Nice!!!"
            };

            //-----------------------------------------------------------------------------------------------------------
            // Act
            //-----------------------------------------------------------------------------------------------------------
            PropertyBag bag = new PropertyBagConverter().Convert(command);
            var actualCommand = (AddNewRecipeCommand)new PropertyBagConverter().Convert(bag);

            //-----------------------------------------------------------------------------------------------------------
            // Assert
            //-----------------------------------------------------------------------------------------------------------
            actualCommand.ShouldHave().AllProperties().EqualTo(command, "a roundtrip conversion should not lose any data.");
        }

        [TestMethod]
        public void When_deserializing_to_a_newer_version_it_should_use_a_post_converter()
        {
            //-----------------------------------------------------------------------------------------------------------
            // Arrange
            //-----------------------------------------------------------------------------------------------------------
            var command = new AddNewRecipeCommand
            {
                Name = "Macaroni with chees",
                Description = "Nice!!!"
            };

            var converter = new PropertyBagConverter();
            converter.AddPostConversion(typeof(AddNewRecipeCommand2), new TestConverter());
            converter.TypeResolver = new TestResolver();

            //-----------------------------------------------------------------------------------------------------------
            // Act
            //-----------------------------------------------------------------------------------------------------------
            PropertyBag bag = converter.Convert(command);
            AddNewRecipeCommand2 command2 = (AddNewRecipeCommand2) converter.Convert(bag);

            //-----------------------------------------------------------------------------------------------------------
            // Assert
            //-----------------------------------------------------------------------------------------------------------
            command.ShouldHave().AllProperties().EqualTo(command2);
            command2.Created.Should().Be(DateTime.Today);
        }

        internal class AddNewRecipeCommand2 : ICommand
        {
            public string Name { get; set; }
            public string Description { get; set; }
            public DateTime Created { get; set; }
            
            public void Validate() { }
        }

        internal class TestConverter : IPropertyBagPostConverter
        {
            public void ApplyConversion(object target, Type targetType, IDictionary<string, object> propertyData)
            {
                var command2 = (AddNewRecipeCommand2) target;
                command2.Created = DateTime.Today;
            }
        }

        internal class TestResolver : IPropertyBagTypeResolver
        {
            public Type Resolve(string className, string nameSpace, string assemblyName)
            {
                return typeof (AddNewRecipeCommand2);
            }
        }
    }
}
